package com.pic.mgt.controller;

import java.util.List;

import com.pic.mgt.log.IgxLog;
import com.pic.mgt.manager.business.BusinessManager;
import com.pic.mgt.monitor.UnitMonitorListener;
import com.pic.mgt.monitor.backup.UnitBackup;
import com.pic.mgt.queue.QueueService;
import com.pic.mgt.unit.Unit;

public abstract class UnitController implements UnitMonitorListener {
	protected BusinessManager businessManager;
	
	private ArrivedBusinessHandler arrivedBusinessHandler;
	
	protected UnitBackup unitBackup;
	
	public UnitController() {
		arrivedBusinessHandler = new ArrivedBusinessHandler();
		arrivedBusinessHandler.startQueueService();
	}
	
	@Override
	public void unitIncoming(List<Unit> unitIncomingList) {
		for (Unit unit : unitIncomingList) {
			this.arrivedBusinessHandler.putElementInQueue(unit);
		}
	}
	
	/**
	 * 停止 Controller 的運作(停止Controller的相關thread運作)。
	 * 呼叫會停止在此方法，一直到thread完成關閉。
	 */
	public void destory() {
		if (this.arrivedBusinessHandler != null) {
			if (this.arrivedBusinessHandler.isWorking()) {
				this.arrivedBusinessHandler.stopQueueService();
			}
		}
	}
	
	/**
	 *  Unit 到達時,方法會被觸發。
	 * @param unit
	 */
	public abstract void doUnitAction(Unit unit);
	
	/**
	 * [Unit 處理監控]
	 * 若Queue內有要處理的Unit，則 newElementArrive()方法會被
	 * 觸發，並附帶上要處理的Unit。	 
	 * @author 洪政緯
	 *
	 */
	private final class ArrivedBusinessHandler
							extends QueueService<Unit> {
		private ArrivedBusinessHandler() {
			super("Arrived Unit Handler");
		}
		
		@Override
		protected void newElementArrive(Unit unit) {
			// 判斷是否為正確的業務名稱,若否則忽略不作動作。
			if (!businessManager.isEffectiveBusiness(unit.getBusinessName())) {
				/*
				 * 判斷 unit name是否為 null。
				 * Unit Name值為 Null只有在Unit 為Message才會發生，因為Message可以容許沒有對
				 * 應的交易檔案存在，此種 Message Unit為較不完全的Unit(缺少unit name,
				 * transaction file等)。若遇到此種讓它繼續往下作，會有對應的處理。(可不必理會
				 * 是無效的業務名稱)
				 */
				if (unit.getUnitName() != null) {
					// ********************** Log **********************
					IgxLog.messageLog.error(UnitController.this,
							"SUDA-208 The unit '{}' has been ignored. Because of ineffective business name '{}'.",
							unit.getUnitName(), unit.getBusinessName());
					// ********************** Log **********************
					
					// 搬移到 Error 目錄
					unitBackup.removeAndBackupErrorUnit(unit.getConfirmationFile());
					
					return;
				}
			}
			
			doUnitAction(unit);
		}
	}

	// --- getter and setter ---
	
	public void setBusinessManager(BusinessManager businessManager) {
		this.businessManager = businessManager;
	}
	
	public void setUnitBackup(UnitBackup unitBackup) {
		this.unitBackup = unitBackup;
	}
}
